home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Night Owl 6
/
Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso
/
039a
/
d3d.zip
/
BSPLSURF.C
< prev
next >
Wrap
Text File
|
1989-11-25
|
11KB
|
349 lines
/* BSPLSURF: B-spline surface.
This program expects as D3D object file in which a grid of points is
defined. The program asks the user to enter m and n: there must be
exactly mn points in the file, numbered 1, 2,... mn. It is assumed
these points are arranged in a grid as follows:
1 2 ... m
m+1 m+2 ... 2m
2m+1 2m+2 ... 3m
. . ... .
. . ... .
. . ... .
(n-1)m+1 (n-1)+2 ... mn
Neither m nor n must be less than 4. The position of the points in
3-D space is free; no two points need have the same x-, y- or z-
coordinates. If the object file contains a section beginning with
"Faces:", then this section si ignored. Two integera M and N are
to be entered; they denote numbers of intervals used in the surface-
fitting process. There will be M intervals between points 1 and 2,
and N intervals between points 1 and m+1, and so on. The B-spline
curved surface that approximates the given points is written to an
output file in the D3D format.
*/
#include <stdio.h>
#include <process.h>
#include <alloc.h>
main()
{
FILE *fp1, *fp2;
char str[30];
float *xx, *yy, *zz, x, y, z, v, u, u2, u3,
a00, a01, a02, a03,
a10, a11, a12, a13,
a20, a21, a22, a23,
a30, a31, a32, a33,
b00, b01, b02, b03,
b10, b11, b12, b13,
b20, b21, b22, b23,
b30, b31, b32, b33,
c00, c01, c02, c03,
c10, c11, c12, c13,
c20, c21, c22, c23,
c30, c31, c32, c33,
x00, x01, x02, x03,
x10, x11, x12, x13,
x20, x21, x22, x23,
x30, x31, x32, x33,
y00, y01, y02, y03,
y10, y11, y12, y13,
y20, y21, y22, y23,
y30, y31, y32, y33,
z00, z01, z02, z03,
z10, z11, z12, z13,
z20, z21, z22, z23,
z30, z31, z32, z33;
int size, i, j, m, n, M, N, mn, l, k, I, J,
A, B, C, ii, jj, nn, mm, P,
h00, h01, h02, h03,
h10, h11, h12, h13,
h20, h21, h22, h23,
h30, h31, h32, h33;
do {
printf("Enter m and n (both at least 4): ");
scanf("%d %d", &m, &n);
}
while (m < 4 || n < 4);
printf("Input file: ");
scanf("%s", str);
if((fp1 = fopen(str, "r")) == NULL) {
printf("No such file");
exit(1);
}
printf("Output file: ");
scanf("%s", str);
if((fp2 = fopen(str, "w")) == NULL) {
printf("File Problem");
exit(1);
}
mn = m*n;
size = (mn+1)*sizeof(float);
xx = malloc(size);
yy = malloc(size);
zz = malloc(size);
for(l=0; l<mn; l++) {
if(fscanf(fp1, "%d %f %f %f", &k, &x, &y, &z) != 4) {
printf("Wrong number of points in file");
exit(1);
}
if(k < 1 || k > mn) {
printf("Point number %d incorrect", k);
exit(1);
}
xx[k] = x;
yy[k] = y;
zz[k] = z;
}
fclose(fp1);
printf("Enter M and N: ");
scanf("%d %d", &M, &N);
/* Let us imagine we have n rows of m points, which gives us
(n-1) * (m-1) rectangles. Among these, only (n-3) * (m-3)
rectangles will be approximated. We consider each of these
rectangles to be divided into M x N tiny rectangles, which
we call 'elements'. There will be A points in the output
file for each horizontal grid line:
*/
A = (m-3) * M + 1;
printf(" i j\n");
for(i=2; i<=n-2; i++)
for(j=2; j<=m-2; j++){
h11 = (i - 1) * m + j;
h10 = h11-1; h12 = h10+2; h13 = h10+3;
h00 = h10-m; h01 = h00+1; h02 = h00+2; h03 = h00+3;
h20 = h10+m; h21 = h20+1; h22 = h20+2; h23 = h20+3;
h30 = h20+m; h31 = h30+1; h32 = h30+2; h33 = h30+3;
printf("%3d %3d\n", i, j); /* Show we are busy */
/* Here the 16 points are numbered as follows:
P00 P01 P02 P03
P10 P11 P12 P13
P20 P21 P22 P23
P30 P31 P32 P33
The inner region, within P11, P12, P21, P22, will be
approximated in this step (with the current values
of i and j). */
x00 = xx[h00]; y00 = yy[h00]; z00 = zz[h00];
x01 = xx[h01]; y01 = yy[h01]; z01 = zz[h01];
x02 = xx[h02]; y02 = yy[h02]; z02 = zz[h02];
x03 = xx[h03]; y03 = yy[h03]; z03 = zz[h03];
x10 = xx[h10]; y10 = yy[h10]; z10 = zz[h10];
x11 = xx[h11]; y11 = yy[h11]; z11 = zz[h11];
x12 = xx[h12]; y12 = yy[h12]; z12 = zz[h12];
x13 = xx[h13]; y13 = yy[h13]; z13 = zz[h13];
x20 = xx[h20]; y20 = yy[h20]; z20 = zz[h20];
x21 = xx[h21]; y21 = yy[h21]; z21 = zz[h21];
x22 = xx[h22]; y22 = yy[h22]; z22 = zz[h22];
x23 = xx[h23]; y23 = yy[h23]; z23 = zz[h23];
x30 = xx[h30]; y30 = yy[h30]; z30 = zz[h30];
x31 = xx[h31]; y31 = yy[h31]; z31 = zz[h31];
x32 = xx[h32]; y32 = yy[h32]; z32 = zz[h32];
x33 = xx[h33]; y33 = yy[h33]; z33 = zz[h33];
a33 = (x00-x03-x30+x33
+ 3*(-x01+x02-x10+x13+x20-x23+x31-x32)
+ 9*(x11-x12-x21+x22))/36;
a32 = (-x00-x02+x30+x32 + 2*(x01-x31)
+ 3*(x10+x12-x20-x22) + 6*(-x11+x21))/12;
a31 = (x00-x02-x30+x32 + 3*(-x10+x12+x20-x22))/12;
a30 = (-x00-x02+x30+x32 + 3*(x10+x12-x20-x22)
+ 4*(-x01+x31) + 12*(x11-x21))/36;
a23 = (-x00+x03-x20+x23 + 2*(x10-x13)
+ 3*(x01-x02+x21-x22) + 6*(x12-x11))/12;
a22 = (x00+x02+x20+x22 + 2*(-x01-x10-x12-x21))/4 + x11;
a21 = (x02-x00-x20+x22 + 2*(x10-x12))/4;
a20 = (x00+x02+x20+x22 - 2*(x10+x12)
+ 4* (x01+x21) - 8*x11)/12;
a13 = (x00-x03-x20+x23 + 3*(x02-x01+x21-x22))/12;
a12 = (-x00-x02+x20+x22 + 2*(x01-x21))/4;
a11 = (x00-x02-x20+x22)/4;
a10 = (-x00-x02+x20+x22 + 4*(-x01+x21))/12;
a03 = (x03-x00-x20+x23 + 3*(x01-x02+x21-x22)
+ 4*(x13-x10) + 12*(x11-x12))/36;
a02 = (x00+x02+x20+x22 - 2*(x01+x21)
+ 4*(x10+x12) - 8*x11)/12;
a01 = (x02-x00-x20+x22 + 4*(x12-x10))/12;
a00 = (x00+x02+x20+x22 + 4*(x01+x10+x12+x21)
+ 16*x11)/36;
b33 = (y00-y03-y30+y33
+ 3*(-y01+y02-y10+y13+y20-y23+y31-y32)
+ 9*(y11-y12-y21+y22))/36;
b32 = (-y00-y02+y30+y32 + 2*(y01-y31)
+ 3*(y10+y12-y20-y22) + 6*(-y11+y21))/12;
b31 = (y00-y02-y30+y32 + 3*(-y10+y12+y20-y22))/12;
b30 = (-y00-y02+y30+y32 + 3*(y10+y12-y20-y22)
+ 4*(-y01+y31) + 12*(y11-y21))/36;
b23 = (-y00+y03-y20+y23 + 2*(y10-y13)
+ 3*(y01-y02+y21-y22) + 6*(y12-y11))/12;
b22 = (y00+y02+y20+y22 + 2*(-y01-y10-y12-y21))/4 + y11;
b21 = (y02-y00-y20+y22 + 2*(y10-y12))/4;
b20 = (y00+y02+y20+y22 - 2*(y10+y12)
+ 4* (y01+y21) - 8*y11)/12;
b13 = (y00-y03-y20+y23 + 3*(y02-y01+y21-y22))/12;
b12 = (-y00-y02+y20+y22 + 2*(y01-y21))/4;
b11 = (y00-y02-y20+y22)/4;
b10 = (-y00-y02+y20+y22 + 4*(-y01+y21))/12;
b03 = (y03-y00-y20+y23 + 3*(y01-y02+y21-y22)
+ 4*(y13-y10) + 12*(y11-y12))/36;
b02 = (y00+y02+y20+y22 - 2*(y01+y21)
+ 4*(y10+y12) - 8*y11)/12;
b01 = (y02-y00-y20+y22 + 4*(y12-y10))/12;
b00 = (y00+y02+y20+y22 + 4*(y01+y10+y12+y21)
+ 16*y11)/36;
c33 = (z00-z03-z30+z33
+ 3*(-z01+z02-z10+z13+z20-z23+z31-z32)
+ 9*(z11-z12-z21+z22))/36;
c32 = (-z00-z02+z30+z32 + 2*(z01-z31)
+ 3*(z10+z12-z20-z22) + 6*(-z11+z21))/12;
c31 = (z00-z02-z30+z32 + 3*(-z10+z12+z20-z22))/12;
c30 = (-z00-z02+z30+z32 + 3*(z10+z12-z20-z22)
+ 4*(-z01+z31) + 12*(z11-z21))/36;
c23 = (-z00+z03-z20+z23 + 2*(z10-z13)
+ 3*(z01-z02+z21-z22) + 6*(z12-z11))/12;
c22 = (z00+z02+z20+z22 + 2*(-z01-z10-z12-z21))/4 + z11;
c21 = (z02-z00-z20+z22 + 2*(z10-z12))/4;
c20 = (z00+z02+z20+z22 - 2*(z10+z12)
+ 4* (z01+z21) - 8*z11)/12;
c13 = (z00-z03-z20+z23 + 3*(z02-z01+z21-z22))/12;
c12 = (-z00-z02+z20+z22 + 2*(z01-z21))/4;
c11 = (z00-z02-z20+z22)/4;
c10 = (-z00-z02+z20+z22 + 4*(-z01+z21))/12;
c03 = (z03-z00-z20+z23 + 3*(z01-z02+z21-z22)
+ 4*(z13-z10) + 12*(z11-z12))/36;
c02 = (z00+z02+z20+z22 - 2*(z01+z21)
+ 4*(z10+z12) - 8*z11)/12;
c01 = (z02-z00-z20+z22 + 4*(z12-z10))/12;
c00 = (z00+z02+z20+z22 + 4*(z01+z10+z12+z21)
+ 16*z11)/36;
/* In the output file we will be using point numbers k,
which are to be computed from the control variables
i, j, I, J. In each rectangle, determined by their
pair (i,j) and to be divided into N x M elements,
we use I, counting up to N, and J counting up to M.
To avoid duplicated points, I and J normally start
at 1, except for the lowest values (2) of i and j:
then I and J start at 0. (Of all rectangles that are
to be divided into elements, the one with i=j=2 is
the leftmost rectangle at the top.) If I=0 (which
implies i=2) then k = (j-2_M + J + 1, otherwise
k = A + (i-2)NA + (I-1)A + (j-2)M + J + 1. This means
that in either case we have:
k = {(i-2)N + I}A + {(j-2)M + 1} + J
A is the total number of mesh points on a horizontal row.
*/
B = (j-2)*M + 1;
for(I=(i == 2 ? 0 : 1); I<=N; I++) {
u = (float)I/N;
u2 = u*u;
u3 = u2*u;
C = ((i-2)*N+I)*A + B;
for(J=(j ==2 ? 0 : 1); J<=M; J++) {
k = C + J;
v = (float)J/M;
x = ((a03*v + a02)*v + a01)*v + a00 +
u*(((a13*v + a12)*v + a11)*v + a10)+
u2*(((a23*v + a22)*v + a21)*v + a20)+
u3*(((a33*v + a32)*v + a31)*v + a30);
y = ((b03*v + b02)*v + b01)*v + b00 +
u*(((b13*v + b12)*v + b11)*v + b10)+
u2*(((b23*v + b22)*v + b21)*v + b20)+
u3*(((b33*v + b32)*v + b31)*v + b30);
z = ((c03*v + c02)*v + c01)*v + c00 +
u*(((c13*v + c12)*v + c11)*v + c10)+
u2*(((c23*v + c22)*v + c21)*v + c20)+
u3*(((c33*v + c32)*v + c31)*v + c30);
fprintf(fp2, "%d %f %f %f\n", k, x, y, z);
}
}
}
fprintf(fp2, "Faces:\n");
nn = (n-3)*N;
mm = A-1; /* mm = (m-3)*M */
for(ii=0; ii<nn; ii++)
for(jj=0; jj<mm; jj++){
P = ii*A + jj + 1;
/* We have to divide each (nearly rectangular) surface
element into two traingles to insure that the points
that will be used as vertices of polygons really lie
in the same plane. The minus sign in, for example,
P -Q R will prevent D3D from drawing line segment PQ.
Since either face of each triangle will be visible,
we specify its vertices both counter-clockwise and
clockwise:
*/
fprintf(fp2, "%d %d %d.\n", P, -(P+A+1), P+1);
fprintf(fp2, "%d %d %d.\n", P+A+1, -P, P+A);
fprintf(fp2, "%d %d %d.\n", P, -(P+A+1), P+A);
fprintf(fp2, "%d %d %d.\n", P+A+1, -P, P+1);
}
fclose(fp2);
}